@setlocal enabledelayedexpansion

:: DEBUG is intended for setting echo on globally. Each sub-routine tests
:: for DEBUG and if set VERBOSE is set. As each sub-routine exits VERBOSE
:: unset.
:: Uncomment 'call SET_VERBOSE' where needed to turn on VERBOSE
:: NOTE - DEBUG and VERBOSE still need some work around the use of the @ prefix.
@set DEBUG=
@if not defined DEBUG @echo off

:: Use this to check UAC status
:: - 0x1 means UAC is on and user will be asked for permission
:: - 0x0 means that UAC is off and install/uninstall will run without asking for permission
:: - User with Admin rights is still recommended.
::reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ /v EnableLUA | grep REG | cut -d" " -f 13

:: NOTE - This script is not intended as an example of best practice for a
:: scripted install of Firebird. It is designed to test almost all possible
:: scriptable combinations and is thus far more complicated than a typical
:: install script need be. However, it can be used for testing. Note that chosen
:: settings :: used for each test run are saved into an .inf file, along with a
:: log of the install run.

@goto :MAIN %*
@goto :EOF

::=======================================================
:SET_GLOBAL_ENV
@call :SET_VERBOSE_IF_DEBUG_ON
@if defined DEBUG @echo Entering %0


:: FBINST_EXEC must point to the package we want to test...
if not defined FBINST_EXEC (
    rem - if we have just built firebird we can test the install immediately
    if defined FBBUILD_FILE_ID (
        if defined FBBUILD_FILENAME_SUFFIX (
            @set FBINST_EXEC=%FBBUILD_INSTALL_IMAGES%\Firebird-%FBBUILD_FILE_ID%%FBBUILD_FILENAME_SUFFIX%.exe
        ) else (
            @set FBINST_EXEC=%FBBUILD_INSTALL_IMAGES%\Firebird-%FBBUILD_FILE_ID%.exe
        )
    )
) else (
    rem Set the actual path and filename here - or set it in the environment before running fbit.
    @set FBINST_EXEC=%USERPROFILE%\Desktop\Firebird-4.0.0.2311_0_x64_RC1.exe
)

:: This should be set dynamically, perhaps. But for now it is hard-coded.
@set FIREBIRD_BASE_VER=Firebird_4_0

:: It is possible that successive installs into the same directory may
:: generate different uninstallers but for now we hard code the default.
@set UNINSTALLEXE=unins000.exe

:: The log dir should probably be under %TEMP% (or something like that)
:: In any case we try to create it if it doesn't exist
@set FBINSTALLLOGDIR=%USERPROFILE%\fbit-tests\logs

:: We use this dir to store copies of each install for future comparison
:: Perhaps this should be under the User's dir?
@set FBINSTALLCOPYDIR=%USERPROFILE%\fbit-tests\install_archive

:: This is just the default root directory for all versions of firebird
@set FIREBIRDROOTDIR="%ProgramFiles%\Firebird"

:: This is the default click through install dir.
:: It is created by the installer if it does not exist.
@set FIREBIRD=%FIREBIRDROOTDIR%\%FIREBIRD_BASE_VER%

:: Set this to 1 if you want to see the generated final command in the screen
:: output. Innosetup stores it automatically in the log file so this is not
:: necessary in normal use. Displaying it also makes the screen output harder
:: to read.
@set SHOW_FINAL_CMD=

:: change as reqd, or comment out if ISC_PASSWORD is already set in your env
@set ISC_PASSWORD="secret"

@set TAB=	&

@if not defined DRYRUN (
  if not exist %FBINSTALLLOGDIR% @mkdir %FBINSTALLLOGDIR% >nul 2>nul
  if not exist %FBINSTALLCOPYDIR% @mkdir %FBINSTALLCOPYDIR% >nul 2>nul
)

@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::====SET_GLOBAL_ENV============================================


::=======================================================
:GET_OPTS
@call :SET_VERBOSE_IF_DEBUG_ON
if defined DEBUG @echo Entering %0

:: Automatically parse the commandline and place all valid options into ENV VARS
:: Courtesy of this link:
:: https://stackoverflow.com/questions/3973824/windows-bat-file-optional-argument-parsing
::@setlocal enabledelayedexpansion

:: NOTE 1: These variable names are case insensitive - we can pass CLEAN or
::         clean, for example.
:: NOTE 2: Variables with defaults are impossible to undefine via passing
::         parameters. They must be undefined in code.
:: NOTE 3: Most variables are flags. If a flag has a default it will take the
::         value of the next flag on the command line. For example
::           flag: flagwithdefault:1
::         and this order of params:
::           flagwithdefault flag
::         will end up as
::           flagwithdefault=flag
::         Basically all this means that these variables should not be passed to runtime:
::         INTERACTIVE INSTALL INSTALLTYPE SERVER SERVICE_TASK SUPERSERVER

set "options=APPTASK: CLASSICSERVER: CLEAN: CLIENT: CMD_PARAMS: COMPONENTS: COPYGDSLIB: DEVINST: DRYRUN: FINALCMD: FULL_CMD: FORCE: HELP: INTERACTIVE:1 INSTALL:1 INSTALLTYPE:ServerInstall NOARCHIVE: NOAUTOSTART: NOCANCEL: NOCOPYFBLIB: NOMSG: NOUNINSTALL: PASSWORD: RUN_TIMESTAMP: SCRIPTED: SERVER:1 SILENT: SP: SERVICE_TASK:1 SUPERCLASSIC: SUPERSERVER:1 TASK_LIST:UseSuperServerTask TESTNAME:"" UNINSTALL: VERYSILENT: XRESULT:0"
if defined VERBOSE @echo on
for %%O in (%options%) do (
  for /f "tokens=1,* delims=:" %%A in ("%%O") do (
    set "%%A=%%~B"
  )
)
if defined VERBOSE (
  call :PRINT_VARS
  if NOT defined DEBUG pause
)

:loop
if not "%~1"=="" (
  set "test=!options:*%~1:=! "
  if "!test!"=="!options! " (
      echo Error: Invalid option %~1
  ) else if "!test:~0,1!"==" " (
      set "%~1=1"
  ) else (
      set "%~1=%~2"
      shift
  )
  @if defined VERBOSE (
    @set %1
    if NOT defined DEBUG pause
)
  shift
  goto :loop
)

if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::=======================================================

::=======================================================
:SET_PARAMS
@call :SET_VERBOSE_IF_DEBUG_ON
@if defined DEBUG @echo Entering %0
::@call :SET_VERBOSE

:: Current possible install options (FB4 RC1)
:: [Types] - ServerInstall DeveloperInstall ClientInstall CustomInstall
:: [Components] - ServerComponent DevAdminComponent ClientComponent
:: [Tasks] - UseClassicServerTask UseSuperClassicTask UseSuperClassicTask\UseGuardianTask ^
::  UseSuperServerTask UseSuperServerTask\UseGuardianTask UseApplicationTask UseServiceTask ^
::  AutoStartTask CopyFbClientToSysTask CopyFbClientAsGds32Task

:: Defaults are
:: SetupType=serverinstall
:: Components=servercomponent,devadmincomponent,clientcomponent
:: Tasks=usesuperservertask,useservicetask,autostarttask,copyfbclienttosystask

:: InnoSetup can use MERGETASKS to add non-exclusive tasks to the default list.
:: For example:
::   MERGETASKS="UseSuperServerTask\UseGuardianTask,CopyFbClientAsGds32Task"
:: UNFORTUNATELY we can't negate tasks with ! if delayed variable expansion is
:: used so this option is not very useful to us.
::
:: Instead we use TASKS to entirely redefine the task list. For example:
::   TASKS="UseClassicServerTask,UseApplicationTask,CopyFbClientAsGds32Task"

:: There are other things we could test, maybe one day. See the installer help
:: dialogue or innosetup help for setup commandline params.

:: FBIT uses SCRIPTED to automatically set /SP- /VERYSILENT /SUPPRESSMSGBOXES
:: INTERACTIVE and SCRIPTED are incompatible. INTERACTIVE is default but the
:: variable is never tested.


@if defined SCRIPTED (
    set VERYSILENT=VERYSILENT
    set SP=SP-
    set NOMSG=SUPPRESSMSGBOXES
    set INTERACTIVE=
)

@if defined UNINSTALL (
    set INSTALL=
    @if defined CLEAN ( set CMD_PARAMS=!CMD_PARAMS! /CLEAN )
rem We now have everything we need for uninstall so jump to the end
    goto :SET_CMD_PARAMS
)

:: Fix up any incompatible assignments

@if defined CLASSICSERVER ( set SUPERSERVER=& set SUPERCLASSIC=)
@if defined SUPERCLASSIC ( set SUPERSERVER=& set CLASSICSERVER=)
:: Theoretically this next line is redundant
@if defined SUPERSERVER ( set SUPERCLASSIC=& set CLASSICSERVER=)

@if defined CLIENT ( set INSTALLTYPE=ClientInstall & set DEVINST=& set SERVER=)
@if defined DEVINST (set INSTALLTYPE=DeveloperInstall & set SERVER=)
:: Theoretically this next line is redundant
@if defined SERVER (set INSTALLTYPE=ServerInstall )


:: Now build our task list

@if defined CLASSICSERVER ( set TASK_LIST=UseClassicServerTask)
@if defined SUPERCLASSIC ( set TASK_LIST=UseSuperClassicTask)
:: Theoretically this next line is redundant
@if defined SUPERSERVER ( set TASK_LIST=UseSuperServerTask)

@if defined APPTASK (
    set TASK_LIST=!TASK_LIST!,UseApplicationTask
) else (
    set TASK_LIST=!TASK_LIST!,UseServiceTask
)

@if NOT defined NOAUTOSTART (
  set TASK_LIST=!TASK_LIST!,AutoStartTask
  set INSTALLTYPE=CustomInstall
)

if NOT defined NOCOPYFBLIB (
  set TASK_LIST=!TASK_LIST!,CopyFbClientToSysTask
  set INSTALLTYPE=CustomInstall
)

@if defined COPYGDSLIB (
  set TASK_LIST=!TASK_LIST!,CopyFbClientAsGds32Task
  set INSTALLTYPE=CustomInstall
)

:SET_CMD_PARAMS
:: set up the CMD_PARAMS variable we will use

@if defined FORCE (set CMD_PARAMS=!CMD_PARAMS! /FORCE )

@if defined NOCANCEL (set CMD_PARAMS=!CMD_PARAMS! /NOCANCEL )

:: Setting PASSWORD is only relevant for a server install
@if defined PASSWORD (
    @if defined SERVER (
        set SYSDBAPASSWORD=%ISC_PASSWORD%
        set CMD_PARAMS=!CMD_PARAMS! /SYSDBAPASSWORD=%SYSDBAPASSWORD%
        set INSTALLTYPE=CustomInstall
    )
)

if defined NOMSG set CMD_PARAMS=!CMD_PARAMS! /SUPPRESSMSGBOXES
if defined SILENT set CMD_PARAMS=!CMD_PARAMS! /SILENT
if defined SP set CMD_PARAMS=!CMD_PARAMS! /SP-
if defined VERYSILENT set CMD_PARAMS=!CMD_PARAMS! /VERYSILENT

:: Setting CustomInstall clears the default COMPONENTS list so we
:: must define it manually
@if /I %INSTALLTYPE% == "CustomInstall" (
    @if defined CLIENT ( set COMPONENTS=ClientComponent)
    @if defined DEVINST ( set COMPONENTS=DevAdminComponent,ClientComponent)
) else (
    set COMPONENTS=ServerComponent,DevAdminComponent,ClientComponent
)

if defined INSTALL (
    set FULL_CMD=/TYPE=!INSTALLTYPE! /TASKS="!TASK_LIST!" /COMPONENTS="!COMPONENTS!" !CMD_PARAMS!
) else (
    set FULL_CMD=!CMD_PARAMS!
)

@if defined VERBOSE (
    @call :PRINT_VARS
    if NOT defined DEBUG pause
)
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===SET_PARAMS==========================================

::=======================================================
:PRINT_VARS
:: if a variable is not defined we don't print it, except for critical
:: variables such as FINALCMD that MUST be defined.
@echo Variables set during script execution are:
@set ADIRNAME
@set APPTASK 2>nul
@set CLASSICSERVER 2>nul
@set CLEAN 2>nul
@set CLIENT 2>nul
@set CMD_PARAMS 2>nul
@set COMPONENTS 2>nul
@set COPYGDSLIB 2>nul
@set DEVINST 2>nul
@set DRYRUN 2>nul
@set FBINST_EXEC
@set FINALCMD 2>nul
@set FULL_CMD
@set FORCE 2>nul
@set INTERACTIVE 2>nul
@set INSTALL 2>nul
@set MERGE_TASKS 2>nul
@set NOARCHIVE= 2>nul
@set NOAUTOSTART 2>nul
@set NOCANCEL 2>nul
@set NOCOPYFBLIB 2>nul
@set NOMSG 2>nul
@set NOUNINSTALL 2>nul
@set PASSWORD 2>nul
@set RUN_TIMESTAMP 2>nul
@set SCRIPTED 2>nul
@set SERVICE_TASK 2>nul
@set SERVER 2>nul
@set SERVICE_TASK 2>nul
@set SILENT 2>nul
@set SP 2>nul
@set SUPERCLASSIC 2>nul
@set SUPERSERVER 2>nul
@set TASK_LIST 2>nul
@set TESTNAME 2>nul
@set UNINSTALL 2>nul
@set VERYSILENT 2>nul
@echo.

@goto :EOF
::=======================================================

::=======================================================
:RUN_INSTALLER
@echo.
@echo.
@call :SET_VERBOSE_IF_DEBUG_ON
if defined DEBUG @echo Entering %0 %*
::@call :CHECK_ENV || (@echo Check the values in SET_ENV & goto :EOF )
@call :CHECK_ENV
::@call :RESET_INSTALL_ENV
@call :GET_OPTS %*
@call :SET_PARAMS %*
::@call :SET_VERBOSE
@if defined VERBOSE @echo on
@if defined VERBOSE @echo FULL_CMD is %FULL_CMD%
@if defined VERBOSE ( if NOT defined DEBUG pause )
@call :TIMESTAMP
@set RUN_TIMESTAMP=%TIMESTAMP%
@set INSTALL_TIMESTAMP=%TIMESTAMP%

set FINALCMD=%FBINST_EXEC% %FULL_CMD% /DIR=%FIREBIRD% /LOG=%FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%.log /SAVEINF=%FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%-saved.inf
if defined DRYRUN (
    @echo DRYRUN - Not executing call %FINALCMD%
) else (
    @if defined SHOW_FINAL_CMD @echo Executing %FINALCMD%
    call %FINALCMD%

    @if errorlevel 1 (
    rem  @echo Calling %FBINST_EXEC% failed with %ERRORLEVEL%
        set _err=%ERRORLEVEL%
        call :ISS_ERROR  %_err% %FBINST_EXEC% %FULL_CMD%
        set /A XRESULT+=1
    ) else (
        @echo Calling %FBINST_EXEC%......................SUCCESS!
    )

    @echo.
    @echo Now checking system state...
    if not defined NOCOPYFBLIB (
        call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll good bad err_is_fail
    ) else (
        call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll bad good no_err_is_fail
    )

    if not defined COPYGDSLIB (
        call :CHECKFILEEXISTS c:\windows\system32\gds32.dll bad good no_err_is_fail
    ) else (
        call :CHECKFILEEXISTS c:\windows\system32\gds32.dll good bad err_is_fail
    )
    @echo.
    @call :COPY_INSTALL
    @echo.
)
    @echo.
@echo %0 completed with %XRESULT% errors
@set XRESULT=0
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@echo.
@echo.
@goto :EOF
::===RUN_INSTALLER=================================


::=========================================================
:RUN_UNINSTALLER
@echo.
@echo.
@call :SET_VERBOSE_IF_DEBUG_ON
::@call :SET_VERBOSE
@if defined DEBUG @echo Entering %0 %*
::@call :RESET_INSTALL_ENV
@call :GET_OPTS %* UNINSTALL
@call :SET_PARAMS
::@call :SET_VERBOSE
@if defined VERBOSE @echo on
@if defined VERBOSE call :PRINT_VARS
@if defined VERBOSE @echo FULL_CMD is %FULL_CMD%
@if defined NOUNINSTALL (
  @echo NOUNINSTALL was passed. Exiting %0.
  @goto :EOF
)
@call :TIMESTAMP
@set RUN_TIMESTAMP=%TIMESTAMP%
@set FINALCMD=%FIREBIRD%\%UNINSTALLEXE% %FULL_CMD% /log=%FBINSTALLLOGDIR%\uninstall%RUN_TIMESTAMP%.log
@if defined VERBOSE ( if NOT defined DEBUG (pause) )
@if defined DRYRUN (
    echo DRYRUN - Not executing call %FINALCMD%
    if defined DEBUG @echo Leaving %0
    @call :UNSET_VERBOSE
    @echo.
    @echo.
    goto :EOF
)
    @if defined SHOW_FINAL_CMD @echo Executing %FINALCMD%
    call %FINALCMD% 2>nul
    if errorlevel 1 (
        set _err=%ERRORLEVEL%
    ) else (
        set _err=0
    )
    if %_err% GEQ 1 (
        set _err=%ERRORLEVEL%
        call :ISS_ERROR  %_err% %UNINSTALLEXE% %FULL_CMD%
        set /A XRESULT+=1
    ) else (
        echo Calling %FIREBIRD%\%UNINSTALLEXE% ................SUCCESS!
    )

    rem We need to give time to the uninstaller to clean up
    rem If the install is interactive we need to close the final msg box first
    rem If the install is scripted we need to pause a few seconds.
    rem Change as required for your system.
    if INTERACTIVE equ 1 (
        echo Close the uninstaller dialog now!!!
        timeout /t 10
    ) else (
        timeout /t 3
    )

    echo.
    echo Now checking system state...
    call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll bad good no_err_is_fail
    call :CHECKFILEEXISTS c:\windows\system32\gds32.dll bad good no_err_is_fail

    if defined CLEAN (
        call :CHECKSHAREDDLLS
        call :CHECKFILEEXISTS %FIREBIRD% bad good no_err_is_fail
    )
    echo.
    call :COPY_INSTALL
    echo.
)
echo.

echo %0 completed with %XRESULT% errors
set XRESULT=0
if defined DEBUG @echo Leaving %0
call :UNSET_VERBOSE
@echo.
@echo.
@goto :EOF
::====CLICK_THROUGH_UNINSTALL========================


::=====================================
:CHECKFILEEXISTS
if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON

:: DIR returns an error if file not found and zero if file is returned so we
:: have to turn things around a bit if we want to test for a file that SHOULD
:: be removed. In that case no error is a bad sign!
::
:: This sub-routine takes four params
:: - %1 filename or dirname to verify
:: - %2 - string for no error from dir. ie if we expect the file to exist
::        then pass GOOD. If we don't expect it then we pass BAD.
:: - %3 - string to output if DIR throws an error
:: - %4 - flag to indicate if 0 is an error or not
::@call :SET_VERBOSE
if defined VERBOSE @echo on
if defined VERBOSE @echo %*
dir %1 >nul 2>nul
if errorlevel 1 (
  set _err=%ERRORLEVEL%
) else (
  set _err=0
)
if %_err% EQU 0 (
  @echo %TAB% %1 exists - %2 !
) else (
  @echo %TAB% %1 not found - %3 !
)

if "%4"=="err_is_fail" (
  if %_err% GTR 0 (
    set /A XRESULT+=1
    @echo XRESULT++
  )
)
if "%4"=="no_err_is_fail" (
  if %_err% EQU 0 (
    set /A XRESULT+=1
    @echo XRESULT++
  )
)

call :RESET_ERRORLEVEL
@call :UNSET_VERBOSE
if defined DEBUG @echo Leaving %0
@goto :EOF
::===CHECKFILEEXISTS==================================


::=====================================
:CHECKSHAREDDLLS
if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON
@reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs > %TEMP%\shareddlls.txt
@grep --ignore-case --count firebird %TEMP%\shareddlls.txt > %TEMP%\shareddllscount.txt
set /p SHAREDDLLSCOUNT= < %TEMP%\shareddllscount.txt
if NOT defined DEBUG del /q %TEMP%\shareddll*.txt
if %SHAREDDLLSCOUNT% GTR 0 (
    @echo %TAB% Oops - residue in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
    set /A XRESULT+=1
    @echo XRESULT++
)
call :RESET_ERRORLEVEL
if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===CHECKSHAREDDLLS===================


::=====================================
:COPY_INSTALL
@call :SET_VERBOSE_IF_DEBUG_ON
if defined DEBUG @echo Entering %0
::@call :SET_VERBOSE
if defined VERBOSE @echo on

:: ADIRNAME should normally be set during install and persist for uninstall
@if not defined ADIRNAME (
    @if defined INSTALL_TIMESTAMP (
        @if defined TESTNAME (
            @set ADIRNAME=%FBINSTALLCOPYDIR%\%FIREBIRD_BASE_VER%_%INSTALLTYPE%_%TESTNAME%_%INSTALL_TIMESTAMP%
        ) else (
            @set ADIRNAME=%FBINSTALLCOPYDIR%\%FIREBIRD_BASE_VER%_%INSTALLTYPE%_%INSTALL_TIMESTAMP%
        )
    ) else (
        @set ADIRNAME=%FBINSTALLCOPYDIR%\%FIREBIRD_BASE_VER%_Uninstall_%RUN_TIMESTAMP%
    )
)
@if defined verbose @echo ADIRNAME is %ADIRNAME%
@mkdir %ADIRNAME% 2>nul

@if defined INSTALL (
    @if not defined NOARCHIVE (
        @echo %TAB% Copying Install to %ADIRNAME%
        @xcopy /e /i /y %FIREBIRD% %ADIRNAME%  > nul
        @if errorlevel 1 (
            @echo ERROR Failure executing xcopy /e /i /y %FIREBIRD% %ADIRNAME%
        )
    )
    @copy %FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%-saved.inf %ADIRNAME%\install-saved.inf > nul
    @copy %FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%.log %ADIRNAME%\install.log > nul
) else (
    @echo %TAB% Copying uninstall log to %ADIRNAME%
    @copy %FBINSTALLLOGDIR%\uninstall%RUN_TIMESTAMP%.log %ADIRNAME%\uninstall.log > nul
)
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===COPY_INSTALL======================

::=====================================
:CHECK_ENV
:: TODO - add more checks for the environment declared in SET_GLOBAL_ENV
if not exist %FBINST_EXEC% (
    echo Cannot find %FBINST_EXEC%
    exit /b 1
)
@goto :EOF
::===CHECK_ENV=========================

::=====================================
:RESET_ERRORLEVEL
:: ERRORLEVEL is an internal variable. We can see its value with
:: 'echo %ERRORLEVEL%' but if we try to reset its value with
:: SET ERRORLEVEL=0 we just create an env var called ERRORLEVEL which will
:: not have the same value as the internal ERRORLEVEL. We have to execute an
:: arbitrary command that cannot fail if we want to really reset the internal
:: variable.
@ver > nul
@goto :EOF
::===RESET_ERRORLEVEL==================

::=====================================
:SET_VERBOSE_IF_DEBUG_ON
:: The script is designed to allow turning VERBOSE on at the sub-routine level
:: If we set DEBUG globally then we should turn on VERBOSE automatically when
:: we enter a sub-routine
@if defined DEBUG (
  @set VERBOSE=1
  @echo on
)
@goto :EOF
::===SET_VERBOSE_IF_DEBUG_ON================

::=====================================
:SET_VERBOSE
@set VERBOSE=1
@goto :EOF
::===SET_VERBOSE================

::=====================================
:UNSET_VERBOSE
:: Unset VERBOSE before exiting each sub-routine.
:: and force echo off
@if NOT defined DEBUG (
  @set VERBOSE=
  @echo off
)
@goto :EOF
::===UNSET_VERBOSE================


::=====================================
:HELP
@echo off
@echo.
@more /e /t4 %~d0%~p0fbit-help.txt
@echo.
goto :EOF
::===HELP==============================

::=====================================
:ISS_ERROR
@echo.
@echo InnoSetup ErrorCode %1 from calling %~2 %~3 %~4 %~5 %~6 %~7 %~8 %~9
@echo Definition of Innosetup errorcode %1 is to be added later
@echo.
@goto :EOF
::======================================

::================================================================================================================
:: GENERIC SUPPORT ROUTINES FROM HERE TO END ======================================================================
::================================================================================================================

::=====================================
:GET_DATE
if NOT defined DEBUG @echo off
echo. | date | FIND "(mm" > NUL
if errorlevel 1 ((set MD=0) & call :ParseDate DD MM) else ((set MD=1) & call :ParseDate MM DD)
@goto :EOF
:ParseDate
for /f "tokens=1-3 delims=/.- " %%a in ("%DATE%") do (
set %1=%%a
set %2=%%b
set YYYY=%%c
@goto:EOF)
::=====================================

::=====================================
:GET_TIME
if NOT defined DEBUG @echo off
for /f "tokens=1-4 delims=:. " %%a in ("%TIME%") do (
set hh=%%a
set nn=%%b
set ss=%%c
set ms=%%d
@goto :EOF)
::=====================================

::=====================================
:CLEAR_DT_VARS
if NOT defined DEBUG @echo off
set MM=
set DD=
set YYYY=
set hh=
set nn=
set ss=
set ms=
@goto :EOF
::=====================================

::=====================================
:TIMESTAMP
@call :GET_DATE
@call :GET_TIME
@set TIMESTAMP=%YYYY%%MM%%DD%%hh%%nn%%ss%
if defined DEBUG (@echo Timestamp set to %TIMESTAMP%)
call :CLEAR_DT_VARS
@goto :EOF
::=====================================

::==============================================================================
:: MAIN is always the last routine
::==============================================================================

::=====================================
:MAIN
@if defined DEBUG @echo Entering %0 %*
@call :SET_GLOBAL_ENV

@if /I "%1"=="help" (
  @call :HELP
  @goto :EOF
)

:: sometimes it is useful to just tidy up!
@if /I "%1"=="clean" (
  @call :RUN_UNINSTALLER SCRIPTED CLEAN
  @goto :EOF
)

@call :RUN_INSTALLER %*
@call :RUN_UNINSTALLER %*

@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===MAIN==============================

:: CONTINUE with
:: - look at setting up different test recipes and naming them.
:: - Integrate innosetup exit codes and look at error handling
:: - Tidy up the relationship between DEBUG and VERBOSE.
::    - DEBUG should turn on VERBOSE?
::    - VERBOSE should be routine specific.?
::    - DEBUG should persist for entire script run?


:: NOTHING BEYOND THIS POINT===========
:EOF
